package com.boboPlanet.xxl.handler;

import com.boboPlanet.comm.entity.po.LoginUserInfoPO;
import com.boboPlanet.comm.rabbitmq.RabbitMqRoutingConfig;
import com.boboPlanet.comm.utils.DateUtil;
import com.boboPlanet.xxl.mapper.UserXxlJobMapper;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO 用户服务容器 job
 * @Author: mis_wu
 * @Date: 2023/2/16  使用方法：标记当前类为一个容器@Component，里面的带有@XxlJob注解的方法表示一个定时任务
 **/
@Component
@Slf4j
public class UserServiceXxlJob extends IJobHandler {

    /**
     * 定时任务执行器
     */
    @Override
    public void execute() {
       //不用继承IJobHandler
    }

    private static List<LoginUserInfoPO> u1 = new ArrayList<>();
    private static List<LoginUserInfoPO> u2 = new ArrayList<>();
    private static List<LoginUserInfoPO> u3 = new ArrayList<>();

    @Resource
    private UserXxlJobMapper userXxlJobMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 具体任务  todo:实时监控用户状态 登录有效期，登录次数等
     */
    @XxlJob("userJobHandler")
    public void realTimeMonitorUserState(){
        log.info("monitor user state starting ...");
        List<LoginUserInfoPO> normalUsers = userXxlJobMapper.queryAllLoginUserInfo();
        if (normalUsers.isEmpty()){
            return;
        }
        //多线程处理数据区间判断，如果分3个线程处理,则每个线程处理 normalUsers.size() / 3
        this.userListDivision(normalUsers);
        this.userListDivisionHandler(normalUsers);
        //todo:多线程分批处理
//        CompletableFuture.allOf(
//                CompletableFuture.runAsync(()->{
//                    //执行 u1 操作
//                    if (!u1.isEmpty()){
//                        this.userListDivisionHandler(u1);
//                    }
//                }),
//                CompletableFuture.runAsync(()->{
//                    //执行 u2 操作
//                    if (!u1.isEmpty()){
//                        this.userListDivisionHandler(u2);
//                    }
//                }),
//                CompletableFuture.runAsync(()->{
//                    //执行 u3 操作
//                    if (!u1.isEmpty()){
//                        this.userListDivisionHandler(u3);
//                    }
//                })
//        ).join();

        //处理完初始化u
//        u1 = new ArrayList<>();
//        u2 = new ArrayList<>();
//        u3 = new ArrayList<>();
    }

    /**
     * 用户信息分割
     * @param normalUsers List
     */
    private void userListDivision(List<LoginUserInfoPO> normalUsers){
        int index = 1;
        for (LoginUserInfoPO user : normalUsers) {
            if (index == 1){
                u1.add(user);
                index++;
                continue;
            }
            if (index == 2){
                u2.add(user);
                index++;
                continue;
            }
            if (index == 3){
                u3.add(user);
                index = 1;
            }
        }
    }

    /**
     * impl
     * @param normalUsers List
     */
    public void userListDivisionHandler(List<LoginUserInfoPO> normalUsers){
        for (LoginUserInfoPO user : normalUsers) {
            //根据开始登录时间 - 当前时间 > 登录有效期 ， 如果没有开始登录时间,直接将该用户标记为离线
            long startLoginTime = user.getStartLoginTime().getTime();
            //Long startSecond = startLoginTime / (24 * 60 * 60 * 1000);
            long nowDate = DateUtil.getNowDate().getTime();
            //Long nowDateSecond = nowDate / (24 * 60 * 60 * 1000);
            if (user.getLoginValidityDay() == 1){
                //登录有效期 1h
                if (Math.abs(nowDate - startLoginTime) > user.getLoginValidityDay() * 60 * 60 * 1000){
                    //修改状态/下线、清除缓存、发送mq给用户中台清除ThreadLocal
                    this.clearUserLoginInfo(user);
                }
            } else if (user.getLoginValidityDay() == 24){
                //登录有效期 24h
                if (nowDate - startLoginTime > user.getLoginValidityDay() * 60 * 60 * 1000){
                    this.clearUserLoginInfo(user);
                }
            }else {
                //不符合的直接下线、清除缓存、发送mq给用户中台清除ThreadLocal（一般不存在不符合的）
                this.clearUserLoginInfo(user);
            }

        }
    }

    public void clearUserLoginInfo(LoginUserInfoPO user){
        //todo: 直接下线、清除缓存、修改登录状态等操作在接收到 mq 之后修改...
        rabbitTemplate.convertAndSend(RabbitMqRoutingConfig.Xxl_Send_User_State_Exchange,RabbitMqRoutingConfig.Xxl_Send_User_State_Routing_Key,user);
    }


    public static void main(String[] args) {
        CompletableFuture.allOf(
            CompletableFuture.runAsync(()->{
                //执行 u1 操作
                System.out.println("线程1 操作===>"+Thread.currentThread().getName());
            }),
            CompletableFuture.runAsync(()->{
                //执行 u2 操作
                try {
                    TimeUnit.SECONDS.sleep(1);
                }catch (Exception e){
                    log.error(e.getMessage(),e);
                }
                System.out.println("线程2 操作===>"+Thread.currentThread().getName());
            }),
            CompletableFuture.runAsync(()->{
                //执行 u3 操作
                try {
                    TimeUnit.SECONDS.sleep(2);
                }catch (Exception e){
                    log.error(e.getMessage(),e);
                }
                System.out.println("线程3 操作===>"+Thread.currentThread().getName());
            }),
            CompletableFuture.runAsync(()->{
                //执行 u3 操作
                System.out.println("线程4 操作===>"+Thread.currentThread().getName());
            })
        ).join();
    }



}
